
#ifndef AFTERMATH_ALIGNED_MEMORY_HPP_INCLUDED
#define AFTERMATH_ALIGNED_MEMORY_HPP_INCLUDED

#include <cstdint>

namespace aftermath
{
    /** Sufficient memory size to allow for allocation on a specified alignment boundary. */
    template <std::uint64_t t_required, std::int32_t t_align>
    struct sufficient_memory_size
    {
        static const std::uint64_t value = t_required + (t_align - 1);
    };

    template <typename T, std::int32_t t_align>
    struct aligned_memory
    {
        static std::uint64_t size(std::uint64_t required_size)
        {
            return required_size + (t_align - 1);
        }
        
        /** Address on a specified alignment boundary. */
        static T* address(void* const h_memory)
        {
            std::uint64_t address = reinterpret_cast<std::uint64_t>(h_memory);
            if (address == 0UL) return nullptr;
            /** We need to align data to <t_align>-byte boundaries. */
            std::uint64_t offset = (t_align - (address % t_align)) % t_align;
            return reinterpret_cast<T*>(address + offset);
        }
    };
}

#endif // AFTERMATH_ALIGNED_MEMORY_HPP_INCLUDED

